/*
 * $Id$
 */
package ua.org.energy.vkek.site.web;

import com.google.gson.Gson;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.servlet.*;
import ua.org.energy.vkek.site.server.DataIOException;
import ua.org.energy.vkek.site.server.EMF;

public class EMFFilter implements Filter {

    public class DataIOExceptionJson {

        public DataIOExceptionJson(String msg, String stackTrace) {
            this.msg = msg;
            this.stackTrace = stackTrace;
        }
        public final String error="server error";
        public String msg;
        public String stackTrace;
    }
    private static final boolean debug = true;
    // The filter configuration object we are associated with.  If
    // this value is null, this filter instance is not currently
    // configured. 
    private FilterConfig filterConfig = null;
    private boolean isNeedTransaction = false;

    public EMFFilter() {
    }

    private void doBeforeProcessing(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
        isNeedTransaction = BaseJsonServlet.checkParamValue(request.getParameter("action"));
    }

    private void doAfterProcessing(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
        if (debug) {
            log("EMFFilter:DoAfterProcessing");
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {

        if (debug) {
            log("EMFFilter:doFilter()");
        }

        doBeforeProcessing(request, response);

        EntityManager em = null;
        try {
            em = EMF.getEMF().createEntityManager();
            //  em = EMF.getEM();
            if (isNeedTransaction) {
                em.getTransaction().begin();
            }
            EMF.setEM(em);
            chain.doFilter(request, response);
            // Guard against services that already committed transaction
            EMF.safeCommit(em);
            EMF.setEM(null);
        } catch (DataIOException e) {
            DataIOExceptionJson error = new DataIOExceptionJson(e.getMessage(), e.toString());
            response.getWriter().print(new Gson().toJson(error));
        } finally {
            isNeedTransaction = false;
            try {
                if (em != null) {
                    if (em.isOpen()) {
                        if (EMF.safeRollback(em)) {
                            log("Rolling back the transaction");
                        }
                        em.close();
                    } else {
                        log("EntityManager is already closed!");
                    }
                }
            } catch (Throwable t) {
                log("Error closing EntityManager");
            }
        }
        doAfterProcessing(request, response);
    }

    /**
     * Return the filter configuration object for this filter.
     */
    public FilterConfig getFilterConfig() {
        return (this.filterConfig);
    }

    /**
     * Set the filter configuration object for this filter.
     *
     * @param filterConfig The filter configuration object
     */
    public void setFilterConfig(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }

    /**
     * Destroy method for this filter
     */
    @Override
    public void destroy() {
        if (EMF.getEMF() != null) {
            EMF.getEMF().close();
        }
    }

    /**
     * Init method for this filter
     */
    @Override
    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
        if (filterConfig != null) {
            if (debug) {
                log("EMFFilter:Initializing filter");
            }
        }
        destroy();
    }

    /**
     * Return a String representation of this object.
     */
    @Override
    public String toString() {
        if (filterConfig == null) {
            return ("EMFFilter()");
        }
        StringBuilder sb = new StringBuilder("EMFFilter(");
        sb.append(filterConfig);
        sb.append(")");
        return (sb.toString());
    }

    public void log(String msg) {
        filterConfig.getServletContext().log(msg);
    }
}
